#pragma once
#include "d3dutil.h"
#include "LevelElement.h"
#include "Vertex.h"
#include <vector>

class NxActor;

class Terrain : public LevelElement
{
public:
	/**
	* Creates a new Terrain from a file name.
	* @param fileName the location of the terrain.
	* @param nrOfColumns the number of columns in the terrain.
	* @param nrOfRows the number of rows in the terrain.
	* @param tileSize the scale factor for the tiles.
	* @param scaleHeight the scale factor for the height.
	* @param offset a value to add to the height.
	*/

	struct InitInfo
	{
		tstring HeightmapFilename;
		tstring TextureLow;
		tstring TextureBase;
		tstring TextureMid;
		tstring TextureHigh;
		float HeightScale;
		float HeightOffset;
		UINT NumRows;
		UINT NumCols;
		float CellSpacing;
	};
	Terrain(Level *pLevel, InitInfo& info);
	/*
	* Destroys the Terrain object.
	*/
	virtual ~Terrain(void);

	virtual void Initialize(ContentManager *pContentManager);
	virtual void Tick(const InputState & refInputState){}
	virtual void Draw(const RenderContext* pRenderContext);
	virtual void DrawRefraction(const RenderContext* pRenderContext, D3DXPLANE refractionplane);
	virtual void DrawReflection(const RenderContext* pRenderContext, D3DXMATRIX reflectionviewmatrix, D3DXPLANE reflectionplane);
	virtual void DrawShadowMap(const RenderContext* pRenderContext);

	vector<D3DXVECTOR3>& GetBoundingBox() { return m_BoundingBox; }
private:
	void CreateEffect(ContentManager *pContentManager);
	void GetEffectVariables(ID3D10Effect* pEffect);
	void BuildVertexBuffer();
	void BuildIndexBuffer();

	void AddTriangle (unsigned int a, unsigned int b, unsigned c);
	void AddQuad (unsigned int a, unsigned int b, unsigned c, unsigned d);
	bool LoadHeightMap();
	void CreateVerticesAndTriangles();
	void DefineInputlayout();
	void CreatePhysicsTerrain();

	void Smooth();
	float Average(UINT i, UINT j);
	bool InBounds(UINT i, UINT j);
	void CalcNormal(unsigned int a, unsigned int b, unsigned int c);
	void GenerateBlendMap();
	unsigned int GetNumVertices();	
	unsigned int GetNrOfTriangles();
			

	unsigned int m_NumColumns;
	unsigned int m_NumRows;
	float m_TileSize;
	float m_ScaleHeight;
	float m_Offset;

	float m_SnowLine;
	float m_RockLine;
	float m_GrassLine;
	float m_SandLine;

	float m_WaterHeight;

	ID3D10InputLayout*			m_pVertexLayout;
	ID3D10Buffer*				m_pVertexBuffer;
	ID3D10Buffer*				m_pIndexBuffer;
	ID3D10Effect*				m_pDefaultEffect;
	ID3D10EffectTechnique*		m_pDefaultTechnique;
	ID3D10EffectTechnique*		m_pShadowTechnique;
	//Textures
	ID3D10ShaderResourceView *	m_pTextureLow;
	ID3D10ShaderResourceView *	m_pTextureBase;
	ID3D10ShaderResourceView *	m_pTextureMid;
	ID3D10ShaderResourceView *	m_pTextureHigh;
	ID3D10ShaderResourceView *	m_pBlendMap;

	ID3D10Texture2D* m_pBlendMapVar;
	//Shader resources for textures
	ID3D10EffectShaderResourceVariable* m_pTextureLowVariable;
	ID3D10EffectShaderResourceVariable* m_pTextureBaseVariabele;
	ID3D10EffectShaderResourceVariable* m_pTextureMidVariabele;
	ID3D10EffectShaderResourceVariable* m_pTextureHighVariabele;
	ID3D10EffectShaderResourceVariable* m_pBlendmapVariabele;
	ID3D10EffectShaderResourceVariable* m_pShadowMapVariabele;

	ID3D10EffectMatrixVariable* m_pWorldViewProjectionVariable;
	ID3D10EffectMatrixVariable* m_pLightWVPVariable;
	ID3D10EffectMatrixVariable* m_pWorldVariable;
	ID3D10EffectVectorVariable* m_pEyePosVariable;
	ID3D10EffectVariable* mfxLightVar;
	ID3D10EffectScalarVariable* m_pHeightOffsetVariable;

	ID3D10EffectScalarVariable* m_pWaterHeghtVariable;
	ID3D10EffectVectorVariable* clipPlanePtr;

	vector<unsigned short> m_VecHeightValues;
	vector<VertexPosNormTex> m_VecVertices;
	vector<DWORD> m_VecIndices;

	vector<vector<D3DXVECTOR3>> m_Normallist;

	InitInfo& m_IntInfo;

	D3DXMATRIX m_ReflectionViewMatrix;
	D3DXMATRIX m_LightWVPMatrix;
	bool m_bReflection;
	bool m_bClipping;
	bool m_bShadowmap;
	D3DXPLANE m_Clippingplane;
	vector<D3DXVECTOR3> m_BoundingBox;
	// -------------------------
	// Disabling default copy constructor and default assignment operator.
	// If you get a linker error from one of these functions, your class is internally trying to use them. This is
	// an error in your class, these declarations are deliberately made without implementation because they should never be used.
	// -------------------------
	Terrain(const Terrain& t);
	Terrain& operator=(const Terrain& t);
};
